//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// COM object model: the root object.
//

# include "StdAfx.h"
# include "Resource.h"
# include "COMRoot.h"
# include "Map.h"
# include "Load.h"
# include "Save.h"
# include "Version.h"
# include "Globals.h"

DECLARE_COM_CLASS ("GPSMapEdit.Application.1", "{81588F76-D296-4e3f-9433-829EC3561F57}", CComRoot, REGCLS_SINGLEUSE);

// NOTE: there may be only single instance of CComRoot due to REGCLS_SINGLEUSE flag.
CComRoot * g_pComRoot;

CComRoot::CComRoot () {
	assert (g_pComRoot == NULL);
	g_pComRoot = this;
}

CComRoot::~CComRoot () {
	g_pComRoot = NULL;
}

# include "COMRoot.inl"

STDMETHODIMP CComRoot::get_Version (BSTR * _ret) {
	USES_CONVERSION;
	* _ret = ::SysAllocString (A2OLE (GME_VER_S));
	return S_OK;
}

STDMETHODIMP CComRoot::MinimizeWindow () {
	::ShowWindow (g_hWnd, SW_MINIMIZE);
	return S_OK;
}

STDMETHODIMP CComRoot::RestoreWindow () {
	::ShowWindow (g_hWnd, SW_RESTORE);
	return S_OK;
}

STDMETHODIMP CComRoot::Exit () {
	::PostMessage (g_hWnd, WM_CLOSE, 0, 0);
	return S_OK;
}

STDMETHODIMP CComRoot::Close () {
	::SendMessage (g_hWnd, WM_COMMAND, ID_FILE_CLOSE, 0);
	return S_OK;
}

STDMETHODIMP CComRoot::Open (BSTR _bstrFileName, VARIANT_BOOL _vbAdd, VARIANT_BOOL _vbWait) {
	if (_bstrFileName == NULL || ::SysStringLen (_bstrFileName) == 0) {
		CFileTypeInfo::ShowOpenFile (_vbAdd == VARIANT_FALSE);
		return S_OK;
	}

	USES_CONVERSION;
	LoadMap (OLE2A (_bstrFileName), 0, _vbAdd == VARIANT_FALSE, g_map);

	if (_vbWait != VARIANT_FALSE)
		WaitLoadThread ();

	return S_OK;
}

STDMETHODIMP CComRoot::SaveAs (BSTR _bstrFileName, BSTR _bstrFormat) {
	USES_CONVERSION;

	const CFileTypeInfo * const pSaverInfo = ::SysStringLen (_bstrFormat) > 0 ? CFileTypeInfo::FindSaverInfoByClass (OLE2A (_bstrFormat)) : g_pSaverInfo;
	if (pSaverInfo == NULL)
		return E_INVALIDARG;

	SaveMap (pSaverInfo, OLE2A (_bstrFileName));

	return S_OK;
}

STDMETHODIMP CComRoot::get_FileName (BSTR * _ret) {
	USES_CONVERSION;
	* _ret = ::SysAllocString (A2OLE (g_strFileName));
	return S_OK;
}

STDMETHODIMP CComRoot::get_FileOpenFilter (BSTR * _ret) {
	string_t strFilter;
	CFileTypeInfo::GetOpenFileFilter (strFilter, 0);

	const size_t cFilterLen2 = strFilter.size ()*3;
	wchar_t * const wstrFilter = (wchar_t *) alloca (sizeof (wchar_t)*cFilterLen2);
	const size_t cFilterLen3 = ::MultiByteToWideChar (CP_ACP, 0, strFilter.c_str (), strFilter.size (), wstrFilter, cFilterLen2);

	* _ret = ::SysAllocStringLen (wstrFilter, cFilterLen3);
	return S_OK;
}

STDMETHODIMP CComRoot::get_LastOpenedFiles (long * _ret) {
	* _ret = g_last_file_names.size ();
	return S_OK;
}

STDMETHODIMP CComRoot::LastOpenedFile (long _lIndex, BSTR * _ret) {
	if (_lIndex < 0 || (size_t) _lIndex >= g_last_file_names.size ())
		return E_INVALIDARG;

	file_names_t::const_iterator i = g_last_file_names.begin ();
	std::advance (i, _lIndex);

	USES_CONVERSION;
	* _ret = ::SysAllocString (A2OLE (i->c_str ()));
	return S_OK;
}

///////////////////////////////////////////////////////////////

# include "About.h"

STDMETHODIMP CComRoot::ShowAboutBox (long _hWndParent) {
	::ShowAboutBox (reinterpret_cast<HWND> (_hWndParent));
	return S_OK;
}

# include "Activation.h"

STDMETHODIMP CComRoot::ShowActivationBox (long _hWndParent) {
	ActivateLicense (reinterpret_cast<HWND> (_hWndParent));
	return S_OK;
}

STDMETHODIMP CComRoot::get_IsRegistered (VARIANT_BOOL * _ret) {
	* _ret = g_bRegistered ? VARIANT_TRUE : VARIANT_FALSE;
	return S_OK;
}

///////////////////////////////////////////////////////////////

STDMETHODIMP CComRoot::get_Visible (VARIANT_BOOL * _ret) {
	* _ret = ::IsWindowVisible (g_hWnd) ? VARIANT_TRUE : VARIANT_FALSE;
	return S_OK;
}

STDMETHODIMP CComRoot::put_Visible (VARIANT_BOOL _Val) {
	::ShowWindow (g_hWnd, _Val != VARIANT_FALSE ? SW_SHOWNA : SW_HIDE);
	return S_OK;
}

///////////////////////////////////////////////////////////////

# include "UndoRedo.h"

STDMETHODIMP CComRoot::ResetModified () {
	ResetUndoRedo ();
	g_bModified = false;
	return S_OK;
}
